// Code by Cromwell D. Enage
// April 2009
#ifndef _FULLSAIL_AI_APP_LOADER_H_
#define _FULLSAIL_AI_APP_LOADER_H_

#include <iosfwd>
#include <string>
#include <vector>

namespace fullsail_ai {

	template <typename CharT, typename CharTraits>
	bool
		loadSamples(
		    std::basic_istream<CharT,CharTraits>& inputStream
		  , std::vector<std::basic_string<CharT,CharTraits> >& inputStrings
		  , std::vector<std::basic_string<CharT,CharTraits> >& actionStrings
		  , std::vector<std::vector<double> >& sampleInputs
		  , std::vector<std::vector<double> >& expectedOutputs
		)
	{
		inputStrings.clear();
		actionStrings.clear();
		sampleInputs.clear();
		expectedOutputs.clear();

		std::size_t const MAX_LINE_LENGTH = 80;
		CharT buffer[MAX_LINE_LENGTH];

		while (!inputStream.eof())
		{
			inputStream.getline(buffer, MAX_LINE_LENGTH);

			if ((buffer[0] == '-') && (buffer[1] == '-'))
			{
				break;
			}
			else
			{
				inputStrings.push_back(buffer);
			}
		}

		if (inputStrings.empty())
		{
			return false;
		}

		while (!inputStream.eof())
		{
			inputStream.getline(buffer, MAX_LINE_LENGTH);

			if ((buffer[0] == '-') && (buffer[1] == '-'))
			{
				break;
			}
			else
			{
				actionStrings.push_back(buffer);
			}
		}

		if (actionStrings.empty())
		{
			return false;
		}

		// This variable determines how the Agent object should evaluate
		// the outputs fed-forward by its neural network.
		// Currently there is only one option.
		std::size_t outputType;

		if (!(inputStream >> outputType))
		{
			return false;
		}

		std::vector<double> inputs(inputStrings.size());
		std::vector<double> outputs(actionStrings.size());

		switch (outputType)
		{
			case 0:  // winner-take-all
			{
				while (!inputStream.eof())
				{
					bool isWellFormed = true;

					for (std::size_t i = 0; i < inputs.size(); ++i)
					{
						if (!(inputStream >> inputs[i]))
						{
							isWellFormed = false;
							break;
						}
					}

					if (isWellFormed)
					{
						if (!(inputStream >> outputType))
						{
							break;
						}

						for (std::size_t i = 0; i < outputs.size(); ++i)
						{
							if (i == outputType)
							{
								outputs[i] = 1.0;
							}
							else
							{
								outputs[i] = 0.0;
							}
						}

						sampleInputs.push_back(inputs);
						expectedOutputs.push_back(outputs);
					}
				}

				return !sampleInputs.empty() && !expectedOutputs.empty();
			}

			default:
			{
				return false;
			}
		}
	}
}  // namespace fullsail_ai

#endif  // _FULLSAIL_AI_APP_LOADER_H_

